/* * Copyright 2009-2016 Weibo, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.weibo.api.motan.cluster.loadbalance; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; import com.weibo.api.motan.core.extension.SpiMeta; import com.weibo.api.motan.rpc.Referer; import com.weibo.api.motan.rpc.Request; /** * "低并发优化" 负载均衡 * * <pre> * 1) 低并发度优先: referer的某时刻的call数越小优先级越高 * * 2) 低并发referer获取策略: * 由于Referer List可能很多,比如上百台,如果每次都要从这上百个Referer或者最低并发的几个,性能有些损耗, * 因此 random.nextInt(list.size()) 获取一个起始的index,然后获取最多不超过MAX_REFERER_COUNT的 * 状态是isAvailable的referer进行判断activeCount. * </pre> * * @author maijunsheng * @version 创建时间:2013-6-14 * */ @SpiMeta(name = "activeWeight") public class ActiveWeightLoadBalance<T> extends AbstractLoadBalance<T> { @Override protected Referer<T> doSelect(Request request) { List<Referer<T>> referers = getReferers(); int refererSize = referers.size(); int startIndex = ThreadLocalRandom.current().nextInt(refererSize); int currentCursor = 0; int currentAvailableCursor = 0; Referer<T> referer = null; while (currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize) { Referer<T> temp = referers.get((startIndex + currentCursor) % refererSize); currentCursor++; if (!temp.isAvailable()) { continue; } currentAvailableCursor++; if (referer == null) { referer = temp; } else { if (compare(referer, temp) > 0) { referer = temp; } } } return referer; } @Override protected void doSelectToHolder(Request request, List<Referer<T>> refersHolder) { List<Referer<T>> referers = getReferers(); int refererSize = referers.size(); int startIndex = ThreadLocalRandom.current().nextInt(refererSize); int currentCursor = 0; int currentAvailableCursor = 0; while (currentAvailableCursor < MAX_REFERER_COUNT && currentCursor < refererSize) { Referer<T> temp = referers.get((startIndex + currentCursor) % refererSize); currentCursor++; if (!temp.isAvailable()) { continue; } currentAvailableCursor++; refersHolder.add(temp); } Collections.sort(refersHolder, new LowActivePriorityComparator<T>()); } private int compare(Referer<T> referer1, Referer<T> referer2) { return referer1.activeRefererCount() - referer2.activeRefererCount(); } static class LowActivePriorityComparator<T> implements Comparator<Referer<T>> { @Override public int compare(Referer<T> referer1, Referer<T> referer2) { return referer1.activeRefererCount() - referer2.activeRefererCount(); } } }